﻿using System;
using System.Collections.Generic;
using System.Threading;
using StockTrader.Config;
using StockTrader.Core;
using StockTrader.Platform.Logging;

namespace StockTrader.Utilities.Broker
{
    public class LoginUtils
    {
        // Login worker thread
        public static void Background_LoginCheckerThread(object obj)
        {
            BrokingAccountObject brokerAccountObj = (BrokingAccountObject)obj;
            IBroker iciciDirectAccount = brokerAccountObj.Broker;
            BrokerErrorCode errorCode = BrokerErrorCode.Success;

            while (!brokerAccountObj.DoStopThread)
            {
                //errorCode = iciciDirectAccount.CheckAndLogInIfNeeded(false);
                string traceString = "Periodic login check: " + errorCode.ToString();
                FileTracing.TraceOut(traceString);

                // sleep of 3 minutes
                Thread.Sleep(3000 * 60);
            }
        }

        // Not used currently
        public static void CheckProgramExit(List<SymbolAlgosThread> stockThreads, List<BrokingAccountThread> brokerThreads, ProgramConfigParams config)
        {
            uint exitCheckInterval = 4; // 4 minutes

            // Maximum time the program should run
            #region ProgramRunTime

            DateTime exitTime = DateTime.Now;
            exitTime = config.bRunTillMarketOpen ? MarketUtils.GetMarketCloseTime() : exitTime.AddMinutes(config.runTimeInMinutes);

            #endregion

            // Main thread looping to check program stop condition
            #region MainThreadCheckingProgramExitCondition
            // Loop to check the exit condition of program
            while (true)
            {
                //Thread.Sleep(1000 * 30);
                ProgramRemoteControl remoteControlValue = ProgramRemoteControl.RUN;
                if (config.bProgramRemoteControl)
                {
                    remoteControlValue = RemoteUtils.GetProgramRemoteControlValue();
                }

                // Condition should be either exit only on market close or after user specified run time
                if ((config.bRunTillMarketOpen && !MarketUtils.IsMarketOpen()) ||
                    DateTime.Now > exitTime ||
                    remoteControlValue.Equals(ProgramRemoteControl.STOP) ||
                    remoteControlValue.Equals(ProgramRemoteControl.HIBERNATE))
                {

                    // exit the background worker threads
                    // need to join the threads properly as they might be doing some work 
                    // when they will be abruptly aborted leading to inconsistent state.

                    foreach (BrokingAccountThread brokerThread in brokerThreads)
                    {
                        // signal the login thread to stop and wait for it to complete
                        brokerThread.brokerAccountObj.DoStopThread = true;
                    }
                    // stock threads, signal them to stop work now
                    foreach (SymbolAlgosThread stockThread in stockThreads)
                    {
                        stockThread.BrokerSymbolAlgosObj.DoStopThread = true;
                    }
                    // wait for all stock threads to terminate for graceful exit
                    foreach (SymbolAlgosThread stockThread in stockThreads)
                    {
                        stockThread.thread.Join();
                    }
#if SIMULATION
#else
                    // wait for broker (account login) threads threads to complete
                    foreach (BrokingAccountThread brokerThread in brokerThreads)
                    {
                        brokerThread.thread.Join();
                    }
#endif
                    // Get out of this infinite loop as the time of run is over
                    break;
                }

                // Sleep sometime
                double timeToSleep = !config.bRunTillMarketOpen && (config.runTimeInMinutes < exitCheckInterval) ? config.runTimeInMinutes : exitCheckInterval;
                timeToSleep *= 60 * 1000; // milliseconds
                timeToSleep /= 2;
                Thread.Sleep((int)timeToSleep);
            }

            #endregion
        }

        public static bool IsErrorFatal(BrokerErrorCode errorCode)
        {
            if (errorCode == BrokerErrorCode.NullResponse || errorCode == BrokerErrorCode.OrderCancelFailed ||
                errorCode == BrokerErrorCode.Http || errorCode == BrokerErrorCode.ServerError ||
                errorCode == BrokerErrorCode.TechnicalReason || 
                errorCode == BrokerErrorCode.Success)
            {
                return false;
            }

            return true;
        }
     }
}
